package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"

	"github.com/julienschmidt/httprouter"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

type Student struct {
	Id    int    `gorm:"column:id;type:int;primaryKey" json:"id"`
	Name  string `gorm:"column:name;type:varchar(64);notNull" json:"name"`
	Score int    `gorm:"column:score;type:int;notNull" json:"score"`
	Desc  string `gorm:"column:desc;type:varchar(128)" json:"desc"`
}

func (s *Student) TableName() string {
	return "student"
}
func init() {
	var err error
	dsn := "proxysql:Proxysql@123!@tcp(192.168.25.21:30008)/sql_test?charset=utf8mb4&parseTime=true"
	DB, err = gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("failed to connect database")
	}
}

func modifyNameById(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(b))
	param := p.ByName("id")
	id, err := strconv.Atoi(param)
	if err != nil {
		panic(err)
	}

	var student Student
	result := DB.Where("id = ?", id).First(&student)
	if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		panic(fmt.Errorf("not found id:%d student! err: %v", id, result.Error))
	}

	var studentTmp Student
	err = json.Unmarshal(b, &studentTmp)
	if err != nil {
		panic(err)
	}
	result = DB.Model(&student).Update("score", studentTmp.Score)
	if result.Error != nil {
		panic(result.Error)
	}
}

func getScoreById(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	param := p.ByName("id")
	id, err := strconv.Atoi(param)
	if err != nil {
		panic(err)
	}

	var student Student
	result := DB.Where("id = ?", id).First(&student)
	if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		panic(fmt.Errorf("not found id:%d student! err: %v", id, result.Error))
	}

	content, err := json.Marshal(&student)
	if err != nil {
		panic(err)
	}
	log.Printf("学生id: %d 学生姓名: %s 学生分数: %d\n", student.Id, student.Name, student.Score)

	w.Write(content)
}

func main() {
	// 删除存量数据
	DB.Exec("DROP TABLE student")
	log.Print("删除存量数据成功")

	err := DB.AutoMigrate(&Student{})
	if err != nil {
		fmt.Println(err)
		return
	}
	log.Print("初始化表成功")

	// 插入样本数据
	err = DB.Create([]Student{
		{Name: "aaa", Score: 90},
		{Name: "bbb", Score: 88},
		{Name: "ccc", Score: 70},
		{Name: "ddd", Score: 100},
		{Name: "eee", Score: 23},
	}).Error
	if err != nil {
		fmt.Println(err)
		return
	}
	log.Print("插入样本数据成功")

	//查询插入样本数据结果
	var result []Student
	DB.Find(&result)
	for _, student := range result {
		fmt.Printf("学生id: %d 学生姓名: %s 学生分数: %d\n", student.Id, student.Name, student.Score)
	}

	router := httprouter.New()
	router.PUT("/student/:id", modifyNameById)
	router.GET("/student/:id", getScoreById)
	router.PanicHandler = func(w http.ResponseWriter, r *http.Request, err interface{}) {
		w.WriteHeader(http.StatusInternalServerError) //设置response status
		fmt.Fprintf(w, "%s", err)                     //线上环境不要把原始错误信息返回给前端。测试阶段可以这么搞
	}
	http.ListenAndServe(":5678", router)
}
